import { Paths } from '@/Paths';
import { fetch_all_tags, ITag } from '@/api/fetch_all_tags';
import { Flex } from '@/component/Flex';
import { useConfirmModal } from '@/component/Modal';
import Show from '@/component/Show';
import { Tag } from '@/component/Tag';
import useToast from '@/component/Toast';
import { Text } from '@/gimd';
import classNames from 'classnames';
import dayjs from 'dayjs';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useNavigate, useParams } from 'react-router';
import Pagination from '../../../component/Pagination';
import { ApiHttp } from '../../../network/ApiHttp';
import { GlobalStore } from '../../../store/GlobalStore';
import { ArticleTagsModal } from './ArticleTagsModal';
import { ArticleListItem } from './ListItem';
import styles from './style.module.less';
import Viewer from 'viewerjs';
import 'viewerjs/dist/viewer.min.css';
import { useTri } from '@/useTri';

export default function ArticleListView() {
  const url_params = useParams();
  const navigate = useNavigate();
  const [page_size, set_page_size] = useState(100);
  const [refresh_flag, set_refresh_flag] = useState(0);
  const [current, set_current] = useState(0);
  const [tags, set_tags] = useState<(number | undefined)[]>();

  useEffect(() => {
    set_current(url_params.page ? parseInt(url_params.page, 0) : 0)
    set_tags(url_params.tag ? url_params.tag.split('_').map(v => parseInt(v, 0)) : void 0)
  }, [url_params.tag, url_params.page])

  const [loading, set_loading] = useState(false);
  const [total, set_total] = useState(0);
  const [list, set_list] = useState<any[]>([]);
  const [{ is_me }] = GlobalStore.useStore();
  const nav = useCallback((page?: number, _tag = tags) => {
    if (_tag?.length) {
      const url = Paths.All.Main_With_Tag_Page
        .replace(':page', '' + (page || 0))
        .replace(':tag', '' + _tag.filter(v => v).join('_'));
      navigate(url, { replace: true });
    } else if (typeof page === 'number') {
      const url = Paths.All.Main_With_Page
        .replace(':page', '' + page);
      navigate(url, { replace: true });
    } else {
      const url = Paths.All.Main;
      navigate(url, { replace: true });
    }
  }, [navigate, tags])

  useEffect(() => {
    const root = document.getElementById('root');
    if (root) root.scrollTop = 0;
  }, [list])

  const [{ session_id }] = GlobalStore.useStore()
  useEffect(() => {
    if (Number.isNaN(current) || current < 0) {
      navigate(Paths.All.Main, { replace: true });
      set_current(0);
      return;
    }
    set_loading(true)
    const url = `blog/list`;
    const bdy = { current, pageSize: page_size, tags }
    const controller = new AbortController();
    ApiHttp.post(url, void 0, bdy, { signal: controller.signal })
      .then(r => {
        const total = Math.max(0, r.total ?? 0);
        const list = r.data || [];
        set_list(list)
        set_total(total)
        if (total <= 0) {
          nav()
        } else if (list.length <= 0) {
          const last = Math.floor(total / page_size)
          nav(last)
        }
      })
      .catch(ApiHttp.ignoreAbort)
      .catch((e: any) => console.error(e))
      .finally(() => set_loading(false))
    return () => controller.abort()
  }, [current, page_size, tags, refresh_flag, navigate, nav, session_id])

  const [toast, ctx1] = useToast();

  const ref_delete_article_id = useRef(-1);
  const delete_article = (id: number) => {
    ApiHttp.delete('blog/delete', { id }).then(() => {
      set_list(l => l.filter(v => v.id !== id))
      const idx = list.findIndex(v => v.id)
      if (idx === 0 && list.length === 1 && current > 0)
        set_current(v => v - 1)
      else
        set_refresh_flag(v => ++v)
      toast("文章已删除")
    }).catch((e: any) => {
      toast(e)
    })
  }

  const [ask_for_delete, ctx0] = useConfirmModal({
    children: "确定删除？",
    onOk: e => delete_article(ref_delete_article_id.current)
  })

  const [tags_editing_article_id, set_tags_editing_article_id] = useState<any>();

  const items = useMemo(() => list?.map(v =>
    <ArticleListItem key={v.id}
      articleId={v.id}
      title={v.title}
      tags={v.tags}
      date={dayjs(v.create_time).format('YYYY-MM-DD HH:mm:ss')}
      content={v.breif || "<无内容>"}
      visibility={v.visibility}
      isMe={is_me}
      onClickDelete={() => {
        ref_delete_article_id.current = v.id;
        ask_for_delete()
      }}

      onClickTag={(tag) => {
        const set = new Set(tags);
        set.add(tag.id)
        nav(0, Array.from(set))
      }}
      onClickEditTags={set_tags_editing_article_id}
    />
  ), [list, is_me, ask_for_delete, nav, tags])

  const [all_tag_infos, set_all_tag_infos] = useState<ITag[]>([]);
  useEffect(() => {
    fetch_all_tags().then(r => set_all_tag_infos(r.data || []));
  }, [])

  const showing_tags = useMemo(() => {
    return all_tag_infos.filter(tag => tags?.findIndex(tag_id => tag_id === tag.id)! >= 0)
  }, [all_tag_infos, tags])

  const ref_root = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const ele = ref_root.current;
    if (!ele || !items.length) return;
    const gallery = new Viewer(ele);
    return () => { gallery.destroy() }
  }, [items])

  const [ref_canvas] = useTri()
  return (
    <div className={classNames(styles.entry_list, { [styles.entry_list_loading]: loading })} ref={ref_root}>
      <Show yes={!!showing_tags?.length}>
        <Flex wrap='wrap' gap={5} alignItems='center'>
          <Text type='secondary' size='s'>筛选标签:</Text>
          {showing_tags?.map((tag, idx) => {
            return <Tag closable key={idx} onClose={() => nav(0, showing_tags.map(v => v.id).filter(v => v !== tag.id))}>{tag.title}</Tag>
          })}
        </Flex>
      </Show>

      <canvas ref={ref_canvas} style={{ width: '100%', height: 300, userSelect: 'none' }} draggable={false} />
      {items}
      <ArticleTagsModal
        open={!!tags_editing_article_id}
        article_id={tags_editing_article_id}
        onCancel={() => set_tags_editing_article_id(void 0)}
      />
      <Pagination
        current={current}
        pageSize={page_size}
        total={total}
        onChanged={v => {
          nav(v.current);
          set_current(v.current)
          set_page_size(v.pageSize)
        }}
        getButtonProps={({ index }) => ({
          href: Paths.All.Main_With_Page.replace(':page', '' + index),
          no_jump: true,
          title: `第${index + 1}页`,
        })} />
      {ctx0}
      {ctx1}
    </div>
  )
}

